package com.et.machine.goods

import android.content.Context
import android.net.Uri
import android.util.Log
import com.et.logger.ELog
import com.et.logger.TAGS
import com.et.machine.store.ChannelEntity
import com.et.machine.store.DataBaseUtil
import com.et.machine.store.IChannelDao
import com.et.machine.store.NORMAL
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers


interface IGoodsTrim {
    fun add(apply: ChannelEntity)
    fun adds(apply: MutableList<ChannelEntity>)
    fun remove(apply: ChannelEntity)
    fun clear()
    fun update(apply: ChannelEntity)
}

val globalChannelEntityMap = HashMap<Int, ChannelEntity>()
val globalDiscountMap = HashMap<String, Int>()

class GoodsHelper : IGoodsTrim {

    private var disposable: Disposable? = null


    /**
     * call by user
     */
    fun subscribe(context: Context) {
        if (disposable == null) {
            Log.d(TAGS.machine, "subscribe  goods info change")
            val channelBox = DataBaseUtil.IChannelDaoBox<IChannelDao>()
            if (DataBaseUtil.channelDao(channelBox) == NORMAL) {
                channelBox.dao?.let { it ->
                    disposable = it.all()
                        .subscribeOn(Schedulers.io())
                        .subscribe { channelList ->
                            channelList.forEach {
                                Log.d(TAGS.vending, it.toString())
                                globalChannelEntityMap[it.uid] = it
                                globalDiscountMap[it.barcode] = it.discount
                            }
                            context.contentResolver.notifyChange(GOODS_URI, null)
                        }
                }
            }
        }
    }


    /**
     * call by user
     */
//    fun <T : ViewBinding> subscribe(
//        planCode: Plan = Plan.ET,
//        adapter: Adapter<GoodsInfo, T>
//    ) {
//        when (planCode) {
//            Plan.NO -> AbstractPlanNoneImpl()
//            Plan.ET -> AbstractPlanETImpl()
//            Plan.KL -> AbstractPlanKLImpl()
//            Plan.LT -> AbstractPlanLTImpl()
//        }.apply {
//            filter = this
//            filter(srcList)
//        }
//
//        Log.d(TAGS.vending, "subscribe")
//        if (disposable == null) {
//            val channelBox = DataBaseUtil.IChannelDaoBox<IChannelDao>()
//            if (DataBaseUtil.channelDao(channelBox) == NORMAL) {
//                channelBox.dao?.let {
//                    disposable = it.all().subscribeOn(Schedulers.io())
//                        .subscribe { mapData ->
//                            GoodsInfo.fillMap(mapData).also { size ->
//                                Log.d(
//                                    TAGS.vending,
//                                    "DataBase Goods Changed:${mapData.size} $size  ${filter == null}"
//                                )
//                            }
//
//                            val destList = mutableListOf<GoodsInfo>()
//                            filter?.filter(destList)
//                            mapData.forEach { item ->
//                                Log.d(TAGS.vending, item.toString())
//                            }
//                            GoodsDiffCallBack(srcList, destList).let { callback ->
//                                DiffUtil.calculateDiff(callback, true).also { result ->
//                                    Handler(Looper.getMainLooper()).apply {
//                                        post {
//                                            adapter.dispatchUpdate(result, destList)
//                                            srcList = destList
//                                        }
//                                    }
//                                }
//                            }
//                        }
//                }
//            }
//        }
//    }

    /**
     * call by com.et.core.release, user ignored
     */
    fun unsubscribe() {
        disposable?.dispose()
    }

    companion object {
        private const val AUTHORITY = "com.et.core.provider"
        private const val GOODS_TABLE_NAME = "table_channel"
        val GOODS_URI: Uri = Uri.parse("content://$AUTHORITY/$GOODS_TABLE_NAME")

        @JvmStatic
        fun getInstance() = Holder.holder
    }

    object Holder {
        val holder = GoodsHelper()
    }

    override fun add(apply: ChannelEntity) {
        val box = DataBaseUtil.IChannelDaoBox<IChannelDao>()
        if (DataBaseUtil.channelDao(box) == NORMAL) {
            box.dao?.also { dao ->
                dao.insert(apply).subscribeOn(Schedulers.io()).subscribe()
            }
        }
    }

    override fun adds(apply: MutableList<ChannelEntity>) {
        val box = DataBaseUtil.IChannelDaoBox<IChannelDao>()
        if (DataBaseUtil.channelDao(box) == NORMAL) {
            box.dao?.also {
                it.inserts(apply).subscribeOn(Schedulers.io()).subscribe()
            }
        }
    }

    override fun remove(apply: ChannelEntity) {
        val box = DataBaseUtil.IChannelDaoBox<IChannelDao>()
        if (DataBaseUtil.channelDao(box) == NORMAL) {
            box.dao?.also {
                it.delete(apply).subscribeOn(Schedulers.io()).subscribe()
            }
        }
    }

    override fun clear() {
        val box = DataBaseUtil.IChannelDaoBox<IChannelDao>()
        if (DataBaseUtil.channelDao(box) == NORMAL) {
            box.dao?.also {
                it.delete().subscribeOn(Schedulers.io()).subscribe()
            }
        }
    }

    override fun update(apply: ChannelEntity) {
        val box = DataBaseUtil.IChannelDaoBox<IChannelDao>()
        if (DataBaseUtil.channelDao(box) == NORMAL) {
            box.dao?.also {
                it.update(apply).subscribeOn(Schedulers.io()).subscribe()
            }
        }
    }

    /**
     * for test cat database
     */
    fun cat() {
        ELog.d(TAGS.vending, "vending:test cat database")
        val box = DataBaseUtil.IChannelDaoBox<IChannelDao>()
        if (DataBaseUtil.channelDao(box) == NORMAL) {
            box.dao?.also { it ->
                it.all().subscribe { it1 ->
                    ELog.d(TAGS.vending, "vending:channel entity size = ${it1.size}")
                    it1.forEach {
                        Log.d(TAGS.vending, it.toString())
                    }
                }
            }
        }
    }
}

